package com.pubinfo.passbook.shiro.filter;

import com.alibaba.fastjson.JSONObject;
import com.pubinfo.passbook.common.model.constant.ShiroAccessEnum;
import com.pubinfo.passbook.common.model.vo.base.JsonResult;
import com.pubinfo.passbook.common.model.vo.base.ResultCode;
import com.pubinfo.passbook.shiro.token.JwtToken;
import com.pubinfo.passbook.shiro.token.JwtUtil;
import com.pubinfo.passbook.common.utils.SessionCookieUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
public class MyShiroFilter extends AccessControlFilter {
  
  @Override
  protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
    if (request instanceof HttpServletRequest) {
      return ((HttpServletRequest) request).getMethod().toUpperCase().equals("OPTIONS");
    }
    return false;
  }
  
  @Override
  protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
      setHeader(httpRequest, httpResponse);
      return true;
    }
    return super.preHandle(request, response);
  }
  
  /**
   * 为response设置header，实现跨域
   */
  private void setHeader(HttpServletRequest request, HttpServletResponse response) {
    //跨域的header设置
    response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Methods", request.getMethod());
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
    //防止乱码，适用于传输JSON数据
    response.setHeader("Content-Type", "application/json;charset=UTF-8");
    response.setStatus(HttpStatus.OK.value());
  }
  
  @Override
  protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;
    String requestURI = httpServletRequest.getRequestURI();
    log.info("shiro filter判断是否放行: {}", requestURI);
    
    //客户端的cookie中的ticket判断是否已经登录过的
    String ticketToken = SessionCookieUtils.getCookie(httpServletRequest, "x-token");
    String token = httpServletRequest.getHeader("token");
    if (StringUtils.isNotBlank(ticketToken)) {
      try {
        //校验ticketToken的有效性
        JwtToken jwtToken = new JwtToken(ticketToken);
        //提交给realm进行登录
        getSubject(request, response).login(jwtToken);
        //如果没有
      } catch (Exception e) {
        log.info("token验证失败");
        //  httpServletResponse.sendRedirect("/loginHtml");
      }
      return true;
    } else if (StringUtils.isNotBlank(token)) {
      try {
        if (executeLogin(httpServletRequest, httpServletResponse)) {
          //验证成功直接放行
          return true;
        }
      } catch (Exception e) {
        log.info("token验证失败");
      }
    }
    
    response401(httpServletRequest, httpServletResponse, null);
    return false;
  }
  
  protected boolean executeLogin(ServletRequest request, ServletResponse response) {
    HttpServletRequest servletRequest = (HttpServletRequest) request;
    String token1 = servletRequest.getHeader("x-token");
    log.info("token1:{}", token1);
    
    if (StringUtils.isNotBlank(token1)) {
      String userId = JwtUtil.getUserIdFromToken(token1);
      //如果这里从redis里面获取得到的token
      log.info("execute 获取到的userId为:{}", userId);
      if (StringUtils.isBlank(userId)) {
        return false;
      }
      JwtToken jwtToken = new JwtToken(token1);
      //提交给realm进行登录
      getSubject(request, response).login(jwtToken);
      //如果没有抛出异常则代表登入成功
      return true;
    }
    
    return false;
  }
  
  private void response401(ServletRequest req, ServletResponse resp, String msg) {
    try {
      HttpServletResponse response = WebUtils.toHttp(resp);
      String contentType = "application/json;charset=utf-8";
      response.setStatus(HttpStatus.UNAUTHORIZED.value());
      response.setContentType(contentType);
      
      response.getWriter().append(JSONObject.toJSONString(JsonResult.error(ResultCode.UNAUTHORIZED)));
    } catch (IOException e) {
      log.error(e.getMessage());
    }
  }
}
